/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pagoda.util.cli;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import pagoda.util.Shell;

/**
 *
 * @author kevin
 */
public abstract class Cmdlet {

    private Map<String, Cmdlet> _children
            = new HashMap<String, Cmdlet>();

    private Map<String, ArgumentHandler> _arguments
            = new HashMap<String, ArgumentHandler>();


    public Cmdlet addSubCommand(String name, Cmdlet cmd)
    {
        _children.put(name, cmd);
        return this;
    }

    public Cmdlet addArgument(String name, ArgumentHandler handler)
    {
        _arguments.put(name, handler);
        return this;
    }

    public abstract String getHelpString();
    public abstract int execute();

    public Cmdlet parse(Stack<String> args)
    {
        if(args.empty())
            return null;
        String arg = args.pop();
        if("help".equals(arg))
        {
            displayHelp();
            System.exit(0);
        }
        else if(arg.startsWith("-"))
        {
            String name = arg.substring(1);
            String val = null;
            int eqindx = name.indexOf("=");
            if(eqindx > -1)
            {
                val = name.substring(eqindx + 1);
                name = name.substring(0, eqindx);
            }
            if(_arguments.containsKey(name))
            {
                _arguments.get(name).process(val);
                return this;
            }
            else
            {
                return null;
            }
        }
        else if(_children.containsKey(arg))
        {
            return _children.get(arg).parse(args);
        }
        args.push(arg);
        return null;
    }

    public List<Cmdlet> parse(String[] args)
    {
        Stack<String> sargs = new Stack<String>();
        for(String arg:args)
        {
            sargs.push(arg);
        }
        List<Cmdlet> cmds = new LinkedList<Cmdlet>();

        while(!sargs.empty())
        {
            Cmdlet cmd = parse(sargs);
            if(cmd != null && !cmds.contains(cmd))
                cmds.add(cmd);
            else
                Shell.writeLine("Unhandled argument : '%s'", sargs.peek());
        }

        return cmds;
    }

    public void displayHelp()
    {
        Shell.writeLine("-------------------------------------");
        Shell.writeLine(getHelpString());
        Shell.writeLine("");
        Shell.writeLine("Arguments:");
        for(String key : _arguments.keySet())
        {
            Shell.writeLine("\t%s : %s", key, _arguments.get(key).getHelpString());
        }
        Shell.writeLine("");
        Shell.writeLine("SubCommands:\n");
        for(String cmd : _children.keySet())
        {
            Shell.writeLine("Command : %s", cmd);
            _children.get(cmd).displayHelp();
        }
    }

}
